﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Tracy.CoreLib.Data;
using Tracy.CoreLib;
using System.Collections.Specialized;
using System.Threading;
using CoreLib.Message;
namespace Tracy.Engine
{
    /// <summary>
    /// TracyEngine，主要逻辑在这里实现
    /// </summary>
    public partial class TracyEngine
    {
        private const bool DEBUG_MODE = true;
        private static Object s_lock_engine = new Object();//用于lock块
        private const int RWLOCK_TIMEOUT = 1000;
        private static ReaderWriterLock rwLockFeedSource = new ReaderWriterLock();
        private static ReaderWriterLock rwLockRssFilter = new ReaderWriterLock();
        private static ReaderWriterLock rwLockSiteSchema = new ReaderWriterLock();
        private static ReaderWriterLock rwLockResource = new ReaderWriterLock();

        private bool _engineInitiated = false;
        /// <summary>
        /// 是否已初始化
        /// </summary>
        public bool EngineInitiated
        {
            get { return _engineInitiated; }
        }

        private static TracyBus _bus;
        /// <summary>
        /// Tracy总线
        /// </summary>
        public TracyBus Bus
        {
            get 
            {
                if (_bus == null)
                {
                    lock (s_lock_engine)
                    {
                        if (_bus == null) _bus = new TracyBus(this); 
                    }
                }
                
                return _bus; 
            }
        }


        private void Initiation()
        {
            try
            {
                rwLockFeedSource.AcquireWriterLock(RWLOCK_TIMEOUT);
                rwLockResource.AcquireWriterLock(RWLOCK_TIMEOUT);
                rwLockRssFilter.AcquireWriterLock(RWLOCK_TIMEOUT);
                rwLockSiteSchema.AcquireWriterLock(RWLOCK_TIMEOUT);
                //加载配置文件和用户数据
                Bus.FeedSourceProvider.Load(Bus.TracySettings[Constants.CONST_SETTING_RSSFEEDLISTLOCATION]);
                Bus.SchemaProvider.Load(Bus.TracySettings[Constants.CONST_SETTING_SITESCHEMALISTLOCATION]);
                Bus.ResourceProvider.Load(Bus.TracySettings[Constants.CONST_SETTING_RESOURCELISTLOCATION]);
                Bus.FilterProvider.Load(Bus.TracySettings[Constants.CONST_SETTING_RSSFILTERLISTLOCATION]);
            }
            finally
            {
                rwLockFeedSource.ReleaseWriterLock();
                rwLockResource.ReleaseWriterLock();
                rwLockRssFilter.ReleaseWriterLock();
                rwLockSiteSchema.ReleaseWriterLock();
            }
            //加载插件
            Bus.TracyPlugins.LoadPlugins();
            Bus.TracyDownloader.OnMessageProcessed += new EventHandler<TracyMessageEventArgs>(TracyDownloader_OnMessageProcessed);
            Bus.TracyDownloader.OnQueueModified += new EventHandler<TracyGeneralEventArgs>(TracyDownloader_OnQueueModified);
            Bus.TracyDownloader.OnException += new EventHandler<EventArgsWithData>(TracyDownloader_OnException);
            _engineInitiated = true;
        }



        public static void SaveFile(string filename, string content)
        {
            System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create);
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);
            try
            {
                sw.Write(content);
            }
            finally
            {
                sw.Close();
                fs.Close();
            }
        }

        private void SaveFile(IXmlModelProvider provider, string locationName)
        {
            string output = provider.ToXml();
            SaveFile(Bus.TracySettings[locationName], output);
        }
        
        public void SaveSettings()
        {
            try
            {
                rwLockFeedSource.AcquireReaderLock(RWLOCK_TIMEOUT);
                rwLockResource.AcquireReaderLock(RWLOCK_TIMEOUT);
                rwLockRssFilter.AcquireReaderLock(RWLOCK_TIMEOUT);
                rwLockSiteSchema.AcquireReaderLock(RWLOCK_TIMEOUT);
                SaveFile(Bus.FeedSourceProvider, Constants.CONST_SETTING_RSSFEEDLISTLOCATION);
                SaveFile(Bus.SchemaProvider, Constants.CONST_SETTING_SITESCHEMALISTLOCATION);
                SaveFile(Bus.ResourceProvider, Constants.CONST_SETTING_RESOURCELISTLOCATION);
                SaveFile(Bus.FilterProvider, Constants.CONST_SETTING_RSSFILTERLISTLOCATION);
            }
            finally
            {
                rwLockFeedSource.ReleaseReaderLock();
                rwLockResource.ReleaseReaderLock();
                rwLockRssFilter.ReleaseReaderLock();
                rwLockSiteSchema.ReleaseReaderLock();
            }

            Bus.TracyTagManager.SaveSettings();
        }     
        
        public static IXmlModelCollection GetFilteredResult(IManagedXmlModelCollection siteSchemas, IXmlModelCollection rssSources)
        {
            IXmlModelCollection output = new XmlModelCollection();
            foreach (RssFeedSource source in rssSources)
            {
                
                CommonFunctions.AppendCollection(output, GetFilteredResult(siteSchemas, source));
            }
            return output;
        }

        public static IXmlModelCollection GetFilteredResult(IManagedXmlModelCollection siteSchemas, RssFeedSource source)
        {
            return FilterEngine.ApplySchema(source, siteSchemas);
        }

        private void UpdateFeed()
        {
            try
            {
                rwLockFeedSource.AcquireReaderLock(RWLOCK_TIMEOUT);
                Bus.FeedSourceProvider.Update();
            }
            finally
            {
                rwLockFeedSource.ReleaseReaderLock();
            }
        }

        #region Direct Access
        public IXmlModelCollection GetFilteredResult()
        {
            return GetFilteredResult(GetSiteSchemas(), GetRssSources());
        }

        /// <summary>
        /// 从所对应的Rss源中过滤出匹配的Resource
        /// </summary>
        /// <param name="filter">过滤器</param>
        public IXmlModelCollection ExecuteFilter(RssFilter filter)
        {
            return ExecuteFilter(filter, Bus.TracyTagManager.GetTaggedTargets(filter, Constants.CONST_DATA_TYPE_RSSFEEDSOURCE));
        }

        /// <summary>
        /// 从所给定的Rss源中过滤出匹配的Resource
        /// </summary>
        /// <param name="filter">过滤器</param>
        /// <param name="sources">Rss源</param>
        /// <returns></returns>
        public IXmlModelCollection ExecuteFilter(RssFilter filter, IManagedXmlModelCollection sources)
        {
            return FilterEngine.MatchRssItems(sources, filter, GetSiteSchemas());
        }

        public IManagedXmlModelCollection GetSiteSchemas()
        {
            IManagedXmlModelCollection rtn;
            try
            {
                rwLockSiteSchema.AcquireReaderLock(RWLOCK_TIMEOUT);
                rtn = ((IManagedXmlModelCollection)Bus.SchemaProvider.Items).GetCopy();

            }
            finally
            {
                rwLockSiteSchema.ReleaseReaderLock();
            }
            return rtn;
        }

        public IManagedXmlModelCollection GetRssSources()
        {
            IManagedXmlModelCollection rtn;
            try
            {
                rwLockFeedSource.AcquireReaderLock(RWLOCK_TIMEOUT);
                rtn = ((IManagedXmlModelCollection)Bus.FeedSourceProvider.Items).GetCopy();
            }
            finally
            {
                rwLockFeedSource.ReleaseReaderLock();
            }
            return rtn;
        }

        public IManagedXmlModelCollection GetRssFilters()
        {
            IManagedXmlModelCollection rtn;
            try
            {
                rwLockRssFilter.AcquireReaderLock(RWLOCK_TIMEOUT);
                rtn = ((IManagedXmlModelCollection)Bus.FilterProvider.Items).GetCopy();
            }
            finally
            {
                rwLockRssFilter.ReleaseReaderLock();
            }
            return rtn;
        }

        public IManagedXmlModelCollection GetCurrentResources()
        {
            IManagedXmlModelCollection rtn;
            try
            {
                rwLockResource.AcquireReaderLock(RWLOCK_TIMEOUT);
                rtn = ((IManagedXmlModelCollection)Bus.ResourceProvider.Items).GetCopy();
            }
            finally
            {
                rwLockResource.ReleaseReaderLock();
            }
            return rtn;
        }

        public void ShutDown()
        {
            Bus.TracyDownloader.ShutDown();
            killThreadFlag = true;
        }
        #endregion
    }


}
